package hall

import (
	"context"
	"reflect"
	"strings"
	"sync"
	"webgame/internal/constants"
	"webgame/internal/dao"
	"webgame/internal/manager"
	"webgame/internal/model"
	"webgame/internal/model/entity/hall"

	"webgame/pb"
	"webgame/pkg/global"
	"webgame/pkg/queue"

	"github.com/topfreegames/pitaya/v2"
	"github.com/topfreegames/pitaya/v2/logger"
	"google.golang.org/protobuf/proto"
)

var (
	LoginManager *loginManager
	loginOnce    sync.Once
)

type loginManager struct {
	manager.BaseManager
	waitLoginQueue        *queue.BaseQueue //等待登录队列
	onlinePlayerInGameSvr int              //在游戏服务器上的人数
}

func NewLoginManager() *loginManager {
	loginOnce.Do(func() {
		LoginManager = &loginManager{
			waitLoginQueue: queue.NewBaseQueue(reflect.TypeOf("")),
		}
	})
	return LoginManager
}

// 开始登录(loginHandler调用)
func (l *loginManager) StartDoLogin(info *hall.LoginInfo) error {
	err := global.ServerApp.GetThread(constants.LoginThread).(*LoginThread).AddNewLoginMsg(info)
	if err != nil {
		logger.Log.Errorf("[LoginManager] startDoLogin failed,error=%s", err.Error())
		return err
	}

	return nil
}

// 正式登录(RemoteLoginThead调用)
func (l *loginManager) DoLogin(ctx context.Context, loginInfo *hall.LoginInfo) error {
	s := pitaya.GetSessionFromCtx(ctx)
	//检查用户名和密码
	reqCode, err1 := l.checkParams(loginInfo.Account, loginInfo.Password)
	if err1 != nil {
		logger.Log.Errorf("[loginManager] DoLogin failed,err:%s", err1.Error())
		err2 := s.Push(constants.LoginRetRoute, &pb.SCLoginRet{
			Result: proto.Int32(constants.LoginSystemUnknowError),
		})
		logger.Log.Errorf("[loginManager] DoLogin failed,err:%s", err2.Error())
		return err2
	}
	//若不符合规则
	if reqCode != 0 {
		err1 = s.Push(constants.LoginRetRoute, &pb.SCLoginRet{
			Result: proto.Int32(constants.LoginSystemUnknowError),
		})
		logger.Log.Errorf("[loginManager] DoLogin failed,err:%s", err1.Error())
		return err1
	}
	//数据库读取
	rs, err := dao.UserDataDao.Get(&model.Users{Username: loginInfo.Account})
	if err != nil {
		err = s.Push(constants.LoginRetRoute, &pb.SCLoginRet{
			Result: proto.Int32(constants.LoginParamsError),
		})
		return err
	}
	//类型转换
	accountData := rs.(*model.Users)

	//若密码错误
	if accountData.Password != loginInfo.Password {
		err = s.Push(constants.LoginRetRoute, &pb.SCLoginRet{
			Result: proto.Int32(constants.LoginPasswordError),
		})
		return err
	}

	//若用户在Online列表中
	if OnlinePlayerManager.IsOnlinePlayer(accountData.Uid) {

	} else {
		//正常登录
		playerInfo := hall.PlayerInfo{
			Uid:      accountData.Uid,
			Version:  accountData.Version,
			Bet:      accountData.Bet,
			Nickname: accountData.Nickname,
			WebID:    int32(accountData.Webid),
		}

		OnlinePlayerManager.BindPlayerInfo(accountData.Uid, &playerInfo)

		//UID绑定Session
		s.Bind(ctx, string(accountData.Uid))
	}

	return nil
}

func (l *loginManager) Tick(nNow int64) error {
	return nil
}

func (l *loginManager) checkParams(params ...string) (int32, error) {
	if params == nil || len(params) < 2 {
		return constants.LoginParamsError, nil
	}

	username := strings.Trim(params[0], " ")
	password := strings.Trim(params[1], " ")

	if len(username) == 0 || len(password) == 0 {
		return constants.LoginParamsError, nil
	}

	return 0, nil
}

// func (l *loginManager) TestDao() {

// }
